module timer(
  input         i_wb_clk,
  input         i_wb_rst,
  input         i_wb_cyc,
  input         i_wb_stb,
  input         i_wb_we,
  input  [ 2:2] i_wb_adr,
  input  [31:0] i_wb_dat,
  input  [ 3:0] i_wb_sel,
  output        o_wb_ack,
  output [31:0] o_wb_dat,
  output        o_irq
);

// offset 0-1
reg en;
// offset 1-2
reg irq;
// offset 4-8
reg [31:0] reload;

reg [31:0] counter;

wire write_en  = (i_wb_cyc & i_wb_stb & i_wb_we) & i_wb_adr == 1'b0 & i_wb_sel[0];
wire write_irq = (i_wb_cyc & i_wb_stb & i_wb_we) & i_wb_adr == 1'b0 & i_wb_sel[1];

// 若向en写入1则为reload，否则为counter-1
wire [31:0] counter_nxt = (write_en & i_wb_dat[0]) | counter == 32'b0 ? reload : counter-32'b1;

always @(posedge i_wb_clk) begin
  counter <= i_wb_rst ? 32'b0 : counter_nxt;
  if (i_wb_rst) begin
    en <= 1'b0;
    irq <= 1'b0;
    reload <= 32'b0;
  end else begin
    irq <= write_irq ? i_wb_dat[8] : irq | (en & counter == 32'b0);
    if (i_wb_cyc & i_wb_stb & i_wb_we) begin
      if (i_wb_adr[2]) begin
        if (i_wb_sel[0]) reload[ 7: 0] <= i_wb_dat[ 7: 0];
        if (i_wb_sel[1]) reload[15: 8] <= i_wb_dat[15: 8];
        if (i_wb_sel[2]) reload[23:16] <= i_wb_dat[23:16];
        if (i_wb_sel[3]) reload[31:24] <= i_wb_dat[31:24];
      end else begin
        if (i_wb_sel[0]) en <= i_wb_dat[0];
      end
    end
  end
end

wb_ack_gen wb_ack_gen(
  .i_wb_clk(i_wb_clk),
  .i_wb_rst(i_wb_rst),
  .i_wb_cyc(i_wb_cyc),
  .i_wb_stb(i_wb_stb),
  .o_wb_ack(o_wb_ack)
);

assign o_wb_dat = i_wb_adr[2] ? reload : {16'b0, 7'b0, irq, 7'b0, en};
assign o_irq = irq;

endmodule
